﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Antlr.Runtime;
using System.Drawing;

namespace WeakScript
{
    public delegate void LogDelegate(string msg);

    public struct Triad
    {
        public byte com;
        public ushort arg;
    }

    public class Logic
    {
        public List<string> TEXT_CODE;
        public List<string> SHORT_CMD_CODE;
        public List<Triad> TRIAD_CODE;

        bool _compileTime;
        public void SetCompile(bool isCompileValue)
        {
            _compileTime = isCompileValue;
        }

        public Dictionary<string, int> commands;
        public LogDelegate Log;

        private TokenInfo _lastTokenInfo;
        public TokenInfo GetLastTokenInfo() { return _lastTokenInfo; }

        public Logic()
        {
            _compileTime = false;
            Clean();
        }

        public void Clean()
        {

            commands = new Dictionary<string, int>();

            TEXT_CODE = new List<string>();
            SHORT_CMD_CODE = new List<string>();
            TRIAD_CODE = new List<Triad>();


            TokenDescrMap = new Dictionary<string, List<IToken>>();
            TokenInfos = new List<TokenInfo>();

            Registr.Clean();
        }

        public void AddCommand(string str, string arg = "")
        {
            if (arg != "")
            {
                if (str.StartsWith("push") && !str.EndsWith("var"))
                {
                    Registr.ConstsNames.Add(arg);
                }

                if (str.StartsWith("new"))
                {
                    Registr.VarNames.Add(arg);
                }

                if (str.StartsWith("set"))
                {

                }
            }

            if (!_compileTime) return;

            Log(str + " " + arg);

            TEXT_CODE.Add(str + " " + arg);
        }

        public void AddCommandExt(string str, string arg = "")
        {

            if (!_compileTime) return;
            if (!commands.ContainsKey(str)) commands[str] = commands.Count;

            int code = 0;
            if (arg != "")
            {
                if (str.StartsWith("push") && !str.EndsWith("var"))
                {
                    code = Registr.ConstsNames.Count;
                    Registr.ConstsNames.Add(arg);
                }

                if (str.StartsWith("new"))
                {
                    code = Registr.VarNames.Count;
                    Registr.VarNames.Add(arg);
                }

                if (str.StartsWith("set"))
                {
                    code = Registr.VarNames.IndexOf(arg);
                    if (code < 0) code = ushort.MaxValue;
                }
            }



            Log(str + " " + arg);

            TEXT_CODE.Add(str + " " + arg);
            SHORT_CMD_CODE.Add("" + commands[str] + " " + code);
            TRIAD_CODE.Add(new Triad() { com = (byte)commands[str], arg = (ushort)code });
        }

        public class TokenInfo
        {
            public TokenInfo(IToken token, string description)
            {
                Token = token;
                Description = description;
            }

            public IToken Token;
            public string Description;
        }

        public List<TokenInfo> TokenInfos;
        public Dictionary<string, List<IToken>> TokenDescrMap;

        public void ProcessToken(IToken token, string descr = "")
        {            
            if (!TokenDescrMap.ContainsKey(descr)) TokenDescrMap[descr] = new List<IToken>();
            TokenDescrMap[descr].Add(token);

            _lastTokenInfo = new TokenInfo(token, descr);
            TokenInfos.Add(_lastTokenInfo);
        }
    }
}
